package teach

import (
	// "encoding/json"
	"encoding/json"
	"strings"

	"gitee.com/chenhonghua/ginorigin/config/storage/database"
	"gitee.com/chenhonghua/ginorigin/config/storage/redis"
	"gitee.com/chenhonghua/ginorigin/config/system/zap"

	"gorm.io/gorm"
)

type Course struct {
	database.BaseModel
	Title        string     `json:"title" gorm:"column:title;type:varchar(256);not null;index;comment:书名"`
	CourseTypeId int        `json:"courseTypeId,omitempty" gorm:"column:course_type_id;type:bigint;comment:课程类型ID"`
	CourseType   CourseType `json:"courseType,omitempty" gorm:"foreignKey:id;AssociationForeignKey:course_type_id"`
	Chapters     []Chapter  `json:"chapters,omitempty" gorm:"foreignKey:course_id;AssociationForeignKey:id"`
	AuthorId     int        `json:"authorId,omitempty" gorm:"column:author_id;type:bigint;comment:作者ID"`
	Author       Author     `json:"author,omitempty" gorm:"foreignKey:id;AssociationForeignKey:author_id"`
}

func (Course) TableName() string {
	return "demo_course"
}

// 增
func (c Course) Create() (r Course) {
	database.Transaction(func(tx *gorm.DB) error {
		con := database.GetConnection().Model(c).Create(&c) // 增加操作
		con.Where("id=?", c.ID).First(&r)                   // 根据id查询insert结果
		return nil
	})
	zap.LOGGER.Debug("course create result:", zap.Any("r", r))
	return r
}

// 改
func (c Course) Update() error {
	// c.Chapters = nil // 注意：更新操作如果携带了无ID的对象属性（如chapter，author等），则会创建这些对象
	return database.GetConnection().Model(c).Updates(&c).Error
}

// 删
func (c Course) Delete() error {
	return database.GetConnection().Model(c).Delete(&c).Error
}

// 单一结果条件查询
func (c Course) FindByCondition(k, v string) (r Course, err error) {
	s, err := redis.Default.Get(c.TableName() + "_" + k + "_" + v)
	zap.LOGGER.Debug("redis cache:", zap.Any("err", err), zap.Any("s", s))
	if err == nil { // 有缓存
		err = json.Unmarshal([]byte(s), &r)
		zap.LOGGER.Debug("-----------------------------------use redis cache-----------------------------------")
		return r, err
	} else if !strings.EqualFold("redis: nil", err.Error()) { // 没有缓存
		zap.LOGGER.Error("获取redis缓存异常", zap.Error(err))
		return r, err
	}
	query := database.GetConnection().Model(c).Where(k+" = ?", v)
	query = query.Preload("CourseType")    // 关联课程类型
	query = query.Preload("Chapters")      // 关联章节
	query = query.Preload("Author")        // 关联作者
	query = query.Preload("Author.Nation") // 关联国家
	err = query.First(&r).Error
	if err == nil {
		b, _ := json.Marshal(r)
		err = redis.Default.Set(c.TableName()+"_"+k+"_"+v, string(b))
		zap.LOGGER.Debug("database query course succes, redis set:", zap.Any("r.", r), zap.Error(err))
	}
	return r, err
}

// 条件查询
func (c Course) FindBySelf() (r []Course, e error) {
	query := database.GetConnection().Model(c)
	if len(c.Title) > 0 {
		query = query.Where("title = ?", c.Title)
	}
	query = query.Preload("CourseType") // 关联课程类型
	query = query.Find(&r)
	return r, query.Error
}

// 分页查询
func (c Course) PageBySelf(page, size int) (r []Course, t int64, e error) {
	e = database.Transaction(func(tx *gorm.DB) error {
		query := database.GetConnection().Model(c)
		if len(c.Title) > 0 {
			query = query.Where("title = ?", c.Title)
		}
		query = query.Preload("CourseType") // 关联课程类型
		if e = query.Count(&t).Error; e != nil {
			return nil
		}
		query = query.Limit(size).Offset((page - 1) * size) // 分页查询
		query = query.Find(&r)
		return query.Error
	})
	return r, t, e
}

type CourseType struct {
	database.BaseModel
	TypeName string `json:"typeName" gorm:"column:type_name;type:varchar(128);index;unique;not null;comment:名字"`
}

func (CourseType) TableName() string {
	return "demo_course_type"
}

type Chapter struct {
	database.BaseModel
	CourseId    int    `json:"courseId" gorm:"column:course_id;type:bigint;not null;comment:课程ID"`
	Sequence    int    `json:"sequence" gorm:"column:sequence;type:int;not null;comment:顺序"`
	Title       string `json:"title" gorm:"column:title;type:varchar(256);not null;comment:章节名"`
	Summary     string `json:"summary" gorm:"column:summary;type:text;comment:摘要"`
	Description string `json:"description" gorm:"column:description;type:text;comment:描述"`
}

func (Chapter) TableName() string {
	return "demo_chapter"
}

type Author struct {
	database.BaseModel
	Name        string `json:"name" gorm:"column:name;type:varchar(256);index;comment:全名"`
	Nationality int    `json:"nationality" gorm:"column:nationality;type:bigint;comment:国籍（国家ID）"`
	Nation      Nation `json:"nation" gorm:"foreignKey:id;AssociationForeignKey:nationality"`
}

func (Author) TableName() string {
	return "demo_author"
}

type Nation struct {
	database.BaseModel
	CnName              string `json:"cnName" gorm:"column:cn_name;type:varchar(256);not null;unique;index;comment:名称（中文）"`
	EnName              string `json:"enName" gorm:"column:en_name;type:varchar(256);not null;unique;index;comment:名称（英文）"`
	EnglishAbbreviation string `json:"englishAbbreviation" gorm:"column:english_abbreviation;type:char(16);comment:英文缩写"`
}

func (Nation) TableName() string {
	return "demo_nation"
}
